﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.Entities;
using MAF.CRUD;
using Domain;
using MAF.Common;
using Domain.Collections;
using Database.Persistence;
using System.Collections.Specialized;
using System.Security;
using System.Threading;
using System.Security.Principal;
using MAF.User.Security;
using MAF.User.Domain;
using MAF.User.Database.Persistence;

namespace Business
{
    public class Security
    {
        /// <summary>
        /// 通过用户名密码验证用户
        /// </summary>
        /// <param name="name"></param>
        /// <param name="psw"></param>
        /// <returns></returns>
        public static UserIdentity Authenticate(string name, string psw)
        {
            BaseQueryVo vo = new BaseQueryVo();
            if (string.IsNullOrEmpty(name))
                vo.Name = "-_-!!!";  // 防止sqlMap中因为name为空而忽略Name条件，应该不会有人使用这个用户名吧
            else
                vo.Name = name;

            UserCollection uc = UserDB.CreateUser();
            IList<UserInfo> users = uc.Index(vo);
            var len = users.Count;
            if (1 < len)
                throw new Exception("系统错误,多个用户使用同一个登录名");

            if (1 > len)
                throw new Exception("用户不存在，请检查您输入的用户名是否有误");

            UserInfo user = users[0];
            if (user.Password != psw)
                throw new Exception("密码错误");

            // 返回已登录Id
            return new UserIdentity(CombGuid.NewGuid(), user.Id, user.Name);
        }

        /// <summary>
        /// 通过令牌验证用户
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static UserIdentity Authenticate(Guid token,Guid userId)
        {
            UserLogonInfo info = UserDB.CreateUserLogon().Show(token);
            if (null == info)
                return null;

            if (info.UserId != userId)
                throw new SecurityException("验证失败，找不到令牌对应的用户");
                //throw new SecurityException("登录已过期或失效，请重新登录");

            return info.ToUserIdentity();
        }

        /// <summary>
        /// 服务器端登录用户
        /// </summary>
        /// <param name="uid"></param>
        public static void LogonUser(UserIdentity uid,DateTime expired)
        {
            if (null == uid)
                throw new SecurityException("系统错误，调用LogonUser时需要提供UserIdentity对象");

            UserLogonCollection db = UserDB.CreateUserLogon();
            if( null != db.Show(uid.Token) )
                throw new SecurityException("您已经登录，无需再重复登录");
            
            // 记录通行证
            UserLogonInfo info = new UserLogonInfo(uid);
            info.Expired = expired;
            db.Add(info);
        }

        /// <summary>
        /// 服务器端退出用户
        /// </summary>
        /// <param name="token"></param>
        /// <param name="userId"></param>
        public static void LogoutUser(Guid token, Guid userId)
        {
            // 验证当前登录是否存在
            UserIdentity uid = Authenticate(token, userId);

            // 销毁该通行证
            int i = UserDB.CreateUserLogon().Delete(token.ToString());
            if (0 == i)
                throw new Exception("退出失败，登录已失效");
        }

        /// <summary>
        /// 服务器端清理过期的登录
        /// </summary>
        /// <param name="uid"></param>
        public static void ClearExpiredLogon(UserIdentity uid)
        {
            // 查询条件
            BaseQueryVo vo = new BaseQueryVo();
            vo.StringA = uid.UserId.ToString();
            vo.DateTimeA = DateTime.Now;

            // 查询结果
            UserLogonCollection db = UserDB.CreateUserLogon();
            IList<UserLogonInfo> list = db.Index(vo);

            // 清理
            foreach (UserLogonInfo info in list)
            {
                db.Delete(info.Id.ToString());
            }
        }

        /// <summary>
        /// 授权
        /// </summary>
        /// <returns></returns>
        public static bool IsInRole(string role)
        {
            // 授权
            IPrincipal p = Thread.CurrentPrincipal;
            if (null == p)
                return false;

            if (p.GetType() != typeof(UserPrincipal))
                return false;

            return p.IsInRole(role);
        }

        /// <summary>
        /// 用户模块的DBFactory
        /// </summary>
        private static DBFactory UserDB
        {
            get { return DBFactory.GetInstance("User"); }
        }

    }
}
